Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

labhub.py: add migrate_issue plugin #521

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

aabhaas-vaish
Copy link
Contributor

@aabhaas-vaish aabhaas-vaish commented Apr 7, 2018

Introduce migrate_issue plugin that adds ability
to migrate an issue from a source repo to target
repo, both owned by the org.

Issue title, issue description and all comments
are copied with a few additional details appended to
the the description and comments. Source issue is
referenced in the target issue and is closed after
the migration is complete.

Closes #518

Reviewers Checklist

  • Appropriate logging is done.
  • Appropriate error responses.
  • Handle every possible exception.
  • Make sure there is a docstring in the command functions. Hint: Lookout for
    botcmd and re_botcmd decorators.
  • See that 100% coverage is there.
  • See to it that mocking is not done where it is not necessary.

@@ -381,3 +381,100 @@ def pr_stats(self, msg, match):
state=type(self).community_state(pr_count)
)
yield reply

@re_botcmd(pattern=r'^migrate\s+https://github.com/([^/]+)/([^/]+)/+issues/(\d+)\s+https://github.com/([^/]+)/([^/]+)/*$', # Ignore LineLengthBear, PyCodeStyleBear
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make this workable for gitlab repos as well. The whole point of labhub is to provide a unified front for both GitHub and GitLab, and hence the name LabHub 😉

yield 'Second repository not owned by our org.'
return

if (repo_name_orig in self.REPOS) and (repo_name_final in self.REPOS):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use, if not... so we can remove the reduntant if block and the contained pass statement

yield 'Repository does not exist!'
return

if self.TEAMS[self.GH_ORG_NAME + ' maintainers'].is_member(user):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

old_labels = old_issue.labels

except RuntimeError:
yield 'Issue does not exist!'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RuntimeError in IGitt is not always 404s 😅

if str(old_issue.state) == 'closed':
yield 'Issue cannot be migrated as it has been closed already.'
return
else:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else block is not needed, remove it

url1 = 'https://github.com/{}/{}/issues/{}'
new_issue_title = old_issue.title
new_issue_description = old_issue.description.rstrip()
extra_msg = '\n\nMigrated issue from '+url1.format(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe include the author as well? Migrate issue opened by @author from ... so the author the issue follows new issue as well

Copy link
Contributor Author

@aabhaas-vaish aabhaas-vaish Apr 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying the same, but there seems to be some problem with the IGitt module I have installed on my system using pip, as it says author of the issue is not an attribute even though I find this method here: https://gitlab.com/gitmate/open-source/IGitt/blob/master/IGitt/GitHub/GitHubIssue.py and I am not particularly sure why but might be some problem with my system... 😅
screenshot from 2018-04-08 00-26-01

' by @' + str(user)

new_issue = self.REPOS[repo_name_final].create_issue(
new_issue_title, new_issue_description+extra_msg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just concatenate this above, concatenation in function args doesn't look good and is confusing


old_comm = old_issue.comments

for i in range(len(old_comm)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use for comment in old_issue.comments and get rid of few lines of code here 😉

yield 'Second repository not owned by our org.'
return

if (repo_name_orig not in self.REPOS) or (repo_name_final not in self.REPOS):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is longer than allowed. (85 > 80)

Origin: LineLengthBear, Section: all.linelength.

yield 'Repository does not exist!'
return

if (self.TEAMS[self.GH_ORG_NAME + ' maintainers'].is_member(user) == False):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is longer than allowed. (84 > 80)

Origin: LineLengthBear, Section: all.linelength.

new_issue_title = old_issue.title
new_issue_description = old_issue.description.rstrip()
issue_author = old_issue.author.username
extra_msg = '\n\nMigrated issue originally opened by @' + issue_author + \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is longer than allowed. (82 > 80)

Origin: LineLengthBear, Section: all.linelength.


for comment in old_issue.comments:
comm_text = comment.body.rstrip()
comm_url = url1.format(orig_host, org, repo_name_orig, issue_number) + \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is longer than allowed. (84 > 80)

Origin: LineLengthBear, Section: all.linelength.

comm_url = url1.format(orig_host, org, repo_name_orig, issue_number) + \
'#issuecomment-' + str(comment.number)
new_body = comm_text + '\n\nOriginally written by @' + \
comment.author.username + ' on ' + str(comment.updated) + ' UTC' + \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is longer than allowed. (84 > 80)

Origin: LineLengthBear, Section: all.linelength.

url2 = 'https://{}.com/{}/{}/issues/{}'.format(
final_host, org, repo_name_final, new_issue.number)

migrated_comment = 'Issue has been migrated to another [repository](' + \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is longer than allowed. (81 > 80)

Origin: LineLengthBear, Section: all.linelength.

@aabhaas-vaish
Copy link
Contributor Author

Requested changes made, @meetmangukiya

@@ -25,6 +25,7 @@ def setUp(self):

self.mock_org = create_autospec(github3.orgs.Organization)
self.mock_gh = create_autospec(github3.GitHub)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated change.

mock_maint_team.is_member.return_value = False

labhub.TEAMS = {
'coala maintainers': mock_maint_team,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent only 4 spaces

# No issue exists
mock_maint_team.is_member.return_value = True
self.mock_repo.get_issue = Mock(side_effect=RuntimeError('Error message',404))
testbot.assertCommand(cmd.format('coala', 'a', '21','coala','b'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing whitespace between args

'has been closed already')
# Migrate issue
mock_maint_team.is_member.return_value = True
mock_iss = create_autospec(IGitt.GitHub.GitHub.GitHubIssue)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use mock_issue instead of shorted name

@aabhaas-vaish
Copy link
Contributor Author

Requested changes made, @jayvdb

# Migrate issue
mock_maint_team.is_member.return_value = True
mock_issue = create_autospec(IGitt.GitHub.GitHub.GitHubIssue)
issue2 = create_autospec(IGitt.GitHub.GitHub.GitHubIssue)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is one called mock_issue and the other issue2? that is confusing.

try:
assert org == self.GH_ORG_NAME or org == self.GL_ORG_NAME
except AssertionError:
yield 'First repository not owned by our org.'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First & second -> source & target

org2 = match.group(6)
repo_name_final = match.group(7)

try:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace try with if

yield 'Issue cannot be migrated as it has been closed already.'
return

url1 = 'https://{}.com/{}/{}/issues/{}'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isnt a url .. it is a format string.

confusing because here url1 is a format string, but below url2 is a real complete url.

new_issue_title = old_issue.title
new_issue_description = old_issue.description.rstrip() + '\n\n'
issue_author = old_issue.author.username
ext_msg = 'Migrated issue originally opened by @' + issue_author + \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls dont use line continuations (\)

else:
raise RuntimeError(sterr, errno)

if str(old_issue.state) == 'closed':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is safer to check that it is open.
then new states wont surprise everyone.

try:
assert org2 == self.GH_ORG_NAME or org2 == self.GL_ORG_NAME
except AssertionError:
yield 'Second repository not owned by our org.'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is only one message, you can use return 'foo' instead of yield & return

@aabhaas-vaish
Copy link
Contributor Author

Changes made @jayvdb

org = match.group(2)
repo_name_orig = match.group(3)
issue_number = match.group(4)
user = msg.frm.nick
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is a bit strange seeing this variable mixed in amoung all the regex matches.

please read every line of your diff and ask yourself if it can be improved.

@aabhaas-vaish
Copy link
Contributor Author

aabhaas-vaish commented Apr 17, 2018

Made changes as requested, @jayvdb

@@ -381,3 +381,90 @@ def pr_stats(self, msg, match):
state=type(self).community_state(pr_count)
)
yield reply

@re_botcmd(pattern=r'^migrate\s+https://(github|gitlab)\.com/([^/]+)/([^/]+)/+issues/(\d+)\s+https://(github|gitlab)\.com/([^/]+)/([^/]+)/*$', # Ignore LineLengthBear, PyCodeStyleBear
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the regex won't work for gitlab sub groups, see regex for other commands to see how its done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this regex is most likely be duplicated in every command, make a new constant with the regex to match github/gitlab url, and then append it to your command. Do this as part of another issue after this is complete 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@meetmangukiya , I used the same regex as used in unassign_cmd and it uses the same regex. How should I go about this? 😕

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about we only capture the URL here, without using regex to parse it, and then split it with a helper function that can be re-used in each command which takes a git hoster URL ?

if target_repo not in self.REPOS:
return 'Target repository does not exist.'

# Ignore LineLengthBear, PyCodeStyleBear
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

source_url = 'https://{}.com/{}/{}/issues/{}'.format(
source_host, source_org, source_repo, issue_number)

# Ignore LineLengthBear, PyCodeStyleBear
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this and make the string multiline, something like

a = ('some long string which doesnt fit in 80 chars'
     'Next part of the string. This both will be concantenated into one')

source_issue.title, target_issue_desc)
target_issue.labels = source_labels

# Ignore LineLengthBear, PyCodeStyleBear
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

comment_ext = '\n\nOriginally commented by @{} on {} UTC and can be seen [here]({})'

for comment in source_issue.comments:
comm_url = source_url + '#issuecomment-' + str(comment.number)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the case for gitlab comments, use IGitt API to get comment link, if it doesn't exist, make upstream contribution

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be excluding the comment URLs for the current PR and will make another PR when upstream contribution in IGitt is made.

target_issue.labels = source_labels

# Ignore LineLengthBear, PyCodeStyleBear
comment_ext = '\n\nOriginally commented by @{} on {} UTC and can be seen [here]({})'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure the time returned has no UTC offset?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it on it on my own forks and there was no UTC offset included there. However, I wasn't able to find documentation explicitly mentioning anything about offsets 😅

@aabhaas-vaish
Copy link
Contributor Author

Will do @meetmangukiya

@nvzard
Copy link
Member

nvzard commented May 15, 2018

@random-access7 can you please make the requested changes?

@aabhaas-vaish
Copy link
Contributor Author

@nvzard, will do by tonight.

migrate_issue plugin that adds ability to
migrate an issue from a source repo to
target repo, both owned by the org.

Issue title, issue description and all comments
are copied with a few additional details appended
to the description and comments. Source issue is
referenced in the target issue and closed after
the migration is completed.

Closes coala#518
@meetmangukiya
Copy link
Member

@gitmate-bot rebase

@gitmate-bot
Copy link

Hey! I'm GitMate.io! This pull request is being rebased automatically. Please DO NOT push while rebase is in progress or your changes would be lost permanently ⚠️

@gitmate-bot
Copy link

Automated rebase failed! Please rebase your pull request manually via the command line.

Reason:

Command: git rebase base/master

Exit Code: 128

Cause:

error: Failed to merge in the changes.


@meetmangukiya
Copy link
Member

@random-access7 can you please resolve the merge conflicts? And we will make sure it merges before anything else so it doesn't lead to more conflicts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

Add new command: Migrate issue to different repository
5 participants